HAL ADC initialization and configuration functions migration

The goal of this page is to show how to migrate the initialization sequence using STM32CubeMX2:

  • Open STM32CubeMX2 ADC configuration panel.

  • Configure the SW layer HAL.

  • Configure the ADC main features.

  • Configure the ADC advanced features.

  • Configure the ADC GPIO pins.

  • Configure the ADC DMA(s) if the application requires to use the ADC in DMA mode.

  • Configure the NVIC if the application requires the ADC to be used in IT mode.

  • Generate the code.

HAL ADC configuration panel

Create a new project with the STM32CubeMX2, then start the initialization and the main configuration.

Project configuration panel

HAL ADC main features configuration

  • The ADC resolution is set to “12 bit”.

  • The ADC sampling mode is set to “Normal”.

  • Configured the chosen ADC channel.

  • Configured the ADC groups.

ADC main feature configuration

HAL ADC advanced features configuration

Configure the advanced ADC features.

ADC advanced feature configuration

GPIO configuration

Configure GPIO pins.

ADC GPIO configuration

DMA configuration

Configure the DMA for data reception as needed.

ADC DMA configuration

NVIC configuration

Configure the NVIC in case of an interrupt.

ADC NVIC configuration

Generated ADC initialization and de-initialization sequences

The ADC initialization sequence is generated in the mx_adc_hal_init function in the mx_adc1.c file, located in the $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

Related concepts:

STM32CubeMX2 Generated : ADC initialization sequence

Topic

HAL 1 Code Snippet

HAL 2 Code Snippet

Declaration of the handle

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
static hal_adc_handle_t hADC1;
static hal_dma_handle_t hGPDMA1_CH1;

initialization and configuration sequence function, including the clock, GPIO, NVIC, and DMA settings

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  /* Enable ADC1 clock */
  __HAL_RCC_ADC12_CLK_ENABLE();

  if (HAL_RCC_ADCDAC_SetKernelClkSource(HAL_RCC_ADCDAC_CLK_SRC_PSIS) != HAL_OK)
  {
    return NULL;
  }

  /* Configure the global features of the ADC (Clock, Resolution,
     Data Alignment, and number of conversion) */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution            = ADC_RESOLUTION_14B;
  hadc1.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode          = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait      = DISABLE;
  hadc1.Init.ContinuousConvMode    = DISABLE;
  hadc1.Init.NbrOfConversion       = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv      = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;
  hadc1.Init.OversamplingMode      = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure Regular Channel */
  sConfig.Channel      = ADC_CHANNEL_1; // <-- Set your channel here
  sConfig.Rank         = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff   = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset       = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure Analog Watchdog (if needed) */
  // Analog watchdog configuration is not directly available in STM32CubeMX HAL
  // You would use HAL_ADC_AnalogWDGConfig() if needed,
  //  but it's not as flexible as STM32CubeMX2

  /* Configure DMA */
  __HAL_RCC_GPDMA1_CLK_ENABLE();

  hdma_adc1.Instance                 = GPDMA1_Channel1;
  hdma_adc1.Init.Request             = GPDMA1_REQUEST_ADC1;
  hdma_adc1.Init.Direction           = DMA_PERIPH_TO_MEMORY;
  hdma_adc1.Init.PeriphInc           = DMA_PINC_DISABLE;
  hdma_adc1.Init.MemInc              = DMA_MINC_ENABLE;
  hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_adc1.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
  hdma_adc1.Init.Mode                = DMA_NORMAL;
  hdma_adc1.Init.Priority            = DMA_PRIORITY_LOW;
  if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
  {
    Error_Handler();
  }

  __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);

  /* Configure NVIC for ADC and DMA */
  HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(ADC1_IRQn);

  HAL_NVIC_SetPriority(GPDMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(GPDMA1_Channel1_IRQn);
}
hal_adc_handle_t *mx_adc1_hal_init(void)
{

  HAL_RCC_ADC12_EnableClock();

  if (HAL_ADC_Init(&hADC1, HAL_ADC1) != HAL_OK)
  {
    return NULL;
  }

hal_adc_config_t adc_config;
  hal_adc_channel_config_t adc_channel_config;

  adc_config.clock               = HAL_ADC_CLOCK_ASYNC_DIV1;
  adc_config.resolution          = HAL_ADC_RESOLUTION_14_BIT;
  adc_config.trigger_freq_mode   = HAL_ADC_TRIGGER_FREQ_HIGH;
  adc_config.sampling_mode       = HAL_ADC_SAMPLING_MODE_NORMAL;
  HAL_ADC_SetConfig(&hADC1, &adc_config);

  /****************************************************************************/
  /* Configuration of basic features (mandatory)                              */
  /****************************************************************************/

/* ==================== Group Regular ====================*/

  hal_adc_reg_config_t reg_config;
  reg_config.trigger_src        = HAL_ADC_REG_TRIG_SOFTWARE_START;
  reg_config.sequencer_length   = 1;
  reg_config.sequencer_discont  = HAL_ADC_REG_SEQ_DISCONT_DISABLE;
  reg_config.continuous         = HAL_ADC_REG_CONV_SINGLE;
  reg_config.overrun            = HAL_ADC_REG_OVR_DATA_OVERWRITTEN;
  reg_config.data_transfer      = HAL_ADC_REG_DATA_TRANSFER_NONE;
  HAL_ADC_REG_SetConfig(&hADC1, &reg_config);




  /****************************************************************************/
  /* Configuration of additional features (optional)                          */
  /****************************************************************************/
  hal_adc_post_processing_config_t post_processing_config;
  post_processing_config.left_bit_shift           = HAL_ADC_LEFT_BIT_SHIFT_1_BIT;
  post_processing_config.gain_compensation_x1000  = 1000;
  HAL_ADC_SetConfigPostProcessing(&hADC1, &post_processing_config);

  hal_adc_low_power_config_t low_power_config;
  low_power_config.lp_auto_wait       = HAL_ADC_LP_AUTO_WAIT_ENABLE;
  HAL_ADC_SetConfigLowPower(&hADC1, &low_power_config);

  hal_adc_awd_config_t adc_awd_config;

  adc_awd_config.group           = HAL_ADC_GROUP_REGULAR;
  adc_awd_config.channel         = HAL_;
  adc_awd_config.threshold_high  = 4194303;
  adc_awd_config.threshold_low   = 0;
  adc_awd_config.filtering       = HAL_ADC_AWD_FILTERING_NONE;
  HAL_ADC_SetConfigAnalogWD(&hADC1, HAL_ADC_AWD_1, &adc_awd_config);

  hal_adc_ovs_config_t ovs_config;
  ovs_config.scope    = HAL_ADC_OVS_DISABLE;
  ovs_config.discont  = HAL_ADC_OVS_CONT;
  ovs_config.ratio    = 1;
  ovs_config.shift    = HAL_ADC_GetOverSamplingShiftKeepRes(ovs_config.ratio);
  HAL_ADC_SetConfigOverSampling(&hADC1, HAL_ADC_OVS_1, &ovs_config);

  hal_adc_offset_config_t offset_config;

  offset_config.channel              = HAL_;
  offset_config.level                = 4194303;
  offset_config.saturation_signed    = HAL_ADC_OFFSET_SAT_SIGNED_DISABLE;
  offset_config.saturation_unsigned  = HAL_ADC_OFFSET_SAT_UNSIGNED_DISABLE;
  HAL_ADC_SetConfigOffset(&hADC1, HAL_ADC_OFFSET_1, &offset_config);


  /* Set ADC global interruption */
  HAL_CORTEX_NVIC_SetPriority(ADC1_IRQn,
                              HAL_CORTEX_NVIC_PREEMP_PRIORITY_0,
                              HAL_CORTEX_NVIC_SUB_PRIORITY_0);
  HAL_CORTEX_NVIC_EnableIRQ(ADC1_IRQn);

  /* Configure DMA */
  HAL_RCC_GPDMA1_EnableClock();

  if (HAL_DMA_Init(&hGPDMA1_CH1, HAL_GPDMA1_CH1) != HAL_OK)
  {
    return NULL;
  }



  hal_dma_direct_xfer_config_t xfer_cfg_adc1_dma;
  xfer_cfg_adc1_dma.request         = HAL_GPDMA1_REQUEST_ADC1;
  xfer_cfg_adc1_dma.direction       = HAL_DMA_DIRECTION_PERIPH_TO_MEMORY;
  xfer_cfg_adc1_dma.src_inc         = HAL_DMA_SRC_ADDR_FIXED;
  xfer_cfg_adc1_dma.dest_inc        = HAL_DMA_DEST_ADDR_INCREMENTED;
  xfer_cfg_adc1_dma.src_data_width  = HAL_DMA_SRC_DATA_WIDTH_BYTE;
  xfer_cfg_adc1_dma.dest_data_width = HAL_DMA_DEST_DATA_WIDTH_BYTE;
  xfer_cfg_adc1_dma.priority        = HAL_DMA_PRIORITY_LOW_WEIGHT_LOW;

  if (HAL_DMA_SetConfigPeriphDirectXfer(&hGPDMA1_CH1, &xfer_cfg_adc1_dma) != HAL_OK)
  {
    return NULL;
  }
    /* Enable the interruption for GPDMA1_CH1 */
  HAL_CORTEX_NVIC_SetPriority(GPDMA1_CH1_IRQn,
                              HAL_CORTEX_NVIC_PREEMP_PRIORITY_0,
                              HAL_CORTEX_NVIC_SUB_PRIORITY_0);
  HAL_CORTEX_NVIC_EnableIRQ(GPDMA1_CH1_IRQn);

  /* Link DMA handle to ADC handle */
  HAL_ADC_REG_SetDMA(&hADC1, &hGPDMA1_CH1);


  return &hADC1;
}

Deinitialization sequence function

void MX_ADC1_DeInit(void)
{
    /* De-initialize the ADC peripheral */
    HAL_ADC_DeInit(&hadc1);

    /* De-initialize the DMA associated with ADC1, if used */
    HAL_DMA_DeInit(hadc1.DMA_Handle);

    /* Disable ADC1 clock */
    __HAL_RCC_ADC12_FORCE_RESET();
    __HAL_RCC_ADC12_RELEASE_RESET();
    __HAL_RCC_ADC12_CLK_DISABLE();
}
void mx_adc1_hal_deinit(void)
{
  (void)HAL_ADC_DeInit(&hADC1);

  HAL_RCC_ADC12_Reset();
  HAL_RCC_ADC12_DisableClock();
}

IRQ handle function

void ADC1_IRQHandler(void)
{
  HAL_ADC_IRQHandler(&hadc1);
}

void GPDMA1_Channel1_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_adc1);
}
void ADC1_IRQHandler(void)
{
  HAL_ADC_IRQHandler(&hADC1);
}

void GPDMA1_CH1_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hGPDMA1_CH1);
}